<template>
  <BaseDialog
    ref="baseDialogRef"
    :title="title"
    :showDialogFoot="false"
    @closed="closed"
  >
    <template #dialog_body>
      <el-upload
        ref="uploadRef"
        class="photo-upload-dialog upload-demo"
        drag
        v-model:file-list="fileList"
        list-type="picture"
        accept="image/*"
        :data="data"
        :show-file-list="true"
        :headers="{'access_token':store.getters.getToken}"
        :action="action"
        :multiple="limit>1?true:false"
        :limit="limit"
        :on-change="handleChange"
        :on-exceed="uploadExceed"
        :on-success="uploadSuccess"
        :before-upload="beforeUpload"
        :before-remove="beforeRemove"
        :auto-upload="autoUpload"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          将文件拖动到此处，或<em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            <div v-if="autoUpload==false">
              <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload" :disabled="uploadDisabled">开始上传</el-button>
            </div>
            只能上传图片格式
          </div>
        </template>
      </el-upload>
    </template>
  </BaseDialog>
</template>

<script lang="ts" setup>
import BaseDialog from '@/components/base/dialog/BaseDialog.vue';
import {
  computed,
  defineExpose, defineProps, getCurrentInstance, nextTick, ref, withDefaults,
} from 'vue';
import {
  ElMessage, ElMessageBox, UploadProps, UploadRawFile, UploadUserFile,
} from 'element-plus';
import { useStore } from 'vuex';
// 导入自定义加载对话框，因为el-upload上传不走axios，因此要专门处理
import loadingDialog from '@/api/common/loading';

// 接收父组件的值
interface Props {
  dialogWidth?:string, // 对话框宽度
  title?:string, // 对话框标题,前台传入，不用加入添加或编辑的文本。添加或编辑的文本由action属性决定
  showDialogFoot?:boolean, // 是否显示对话框脚部
  limit?:number, // 允许上传的最大数量
  autoUpload?:boolean, // 是否自动上传
  data?:Record<string, any>, // 上传时附带的额外参数
}
const props = withDefaults(defineProps<Props>(), {
  title: '图片上传',
  limit: 1,
  autoUpload: true,
});
const {
  startLoading, endLoading,
} = loadingDialog();
// 文件列表
const fileList = ref<UploadUserFile[]>([]);
// 上传按钮状态
let uploadDisabled = computed(() => {
  if (fileList.value.length > 0) { // 只有选择了文件按钮才回可以点击
    return false;
  }
  return true;
});
const { proxy } = getCurrentInstance(); // 使用proxy代替ctx，因为ctx只在开发环境有效
const store = useStore();
const baseDialogRef = ref();
const action = ref<string>('');
// 打开此对话框的函数
const openDialog = async (url:string) => {
  action.value = url;
  await nextTick();
  baseDialogRef.value.openDialog();
};
// 关闭此对话框的函数
const closeDialog = () => {
  baseDialogRef.value.closeDialog();
};
// 对话框关闭时执行的函数
const uploadRef = ref();
const closed = () => {
  // 清空上传组件信息，但是上传文件的列表无法真正清空，即不显示但是还存在。原因不明
  uploadRef.value.clearFiles();
  // 清空文件列表
  fileList.value = [];
};
// 当文件列表改变时
const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
  // console.log(fileList.value);
};
// 文件超出个数限制时的钩子时执行
const uploadExceed:UploadProps['onExceed'] = (uploadFile, uploadFiles) => { // files是选中但没有在文件列表的图片；fileList在文件列表中的图片集合
  ElMessage.error(`只允许上传${props.limit}个图像`);
};
// 上传文件之前的钩子，参数为上传的文件， 若返回false或者返回 Promise 且被 reject，则停止上传。
const beforeUpload = (rawFile: UploadRawFile) => {
  // console.log('执行上传');
  // 开始加载动画
  startLoading();
};
// 上传成功时执行
const uploadSuccess:UploadProps['onSuccess'] = (response, files, uploadFiles) => { // files是选中但没有在文件列表的图片；fileList在文件列表中的图片集合
  console.log('上传成功');
  // 结束加载动画
  endLoading();
  if (response.success) { // 如果上传成功
    // this.imageUrl=window.URL.createObjectURL(file.raw);//将图片变为已经上传的图片。注意：从本地图片读取而不是服务端
    // fileList.length=0;// 清空文件列表中的图片集合
    proxy.$emit('uploadSuccess'); // 父组件回调
    // 关闭对话框
    closeDialog();
  } else { // 上传失败
    // 清空文件列表
    fileList.value = [];
    ElMessage.error(response.msg);
  }
};
// 删除文件之前的钩子
// 参数为上传的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除。
const beforeRemove:UploadProps['beforeRemove'] = async (uploadFile, uploadFiles) => {
  let result = false;
  await ElMessageBox.confirm(`确定移除文件${uploadFile.name}？`)
    .then(() => {
      result = true;
    }).catch(() => {
      result = false;
    });
  return result;
};
// 执行手动上传
const submitUpload = () => {
  uploadRef.value.submit();
};
defineExpose({ // 参考vue3官方文档，需要将函数暴露出去才能被父组件调用，setup模式是不暴露的
  openDialog,
  closeDialog,
});

</script>

<style lang="scss" scoped>
.photo-upload-dialog{
  ::v-deep .el-upload{
    width:100%;
    .el-upload-dragger{
      width:100%;
    }
  }
  .el-upload__tip{
    text-align:center;
  }
}
</style>
